<?php
// 应用公共文件

/**
 * 获取当前的response 输出类型
 * @access protected
 * @return string
 */
function getResponseType(): string
{
    return request()->isJson() || request()->isAjax() ? 'json' : 'html';
}

/**
 * 操作成功跳转的快捷方法
 * @access protected
 * @param  mixed $msg 提示信息
 * @param  string $url 跳转的URL地址
 * @param  mixed $data 返回的数据
 * @param  integer $wait 跳转等待时间
 * @param  array $header 发送的Header信息
 * @return void
 */
function success($msg = '', string|null $url = null, $data = '', int $wait = 2, array $header = [])
{
    if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
        $url = $_SERVER["HTTP_REFERER"];
    } elseif ($url) {
        $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : (string)\think\facade\Route::buildUrl($url);
    }

    $result = [
        'code' => 1,
        'msg' => $msg,
        'data' => $data,
        'url' => $url,
        'wait' => $wait,
    ];

    $type = getResponseType();
    // 把跳转模板的渲染下沉，这样在 response_send 行为里通过getData()获得的数据是一致性的格式
    if ('html' == strtolower($type)) {
        $type = 'view';
        $response = response(think\facade\View::display(public_path("static") . "dispatch_jump.html", $result), 200, $header, $type);
    } else {
        $response = think\Response::create($result, $type)->header($header);
    }

    // throw new think\exception\HttpResponseException($response);
    return $response;
}

/**
 * 操作错误跳转的快捷方法
 * @access protected
 * @param  mixed $msg 提示信息
 * @param  string $url 跳转的URL地址
 * @param  mixed $data 返回的数据
 * @param  integer $wait 跳转等待时间
 * @param  array $header 发送的Header信息
 * @return void
 */
function error($msg = '', string|null $url = null, $data = '', int $wait = 2, array $header = [])
{
    if (is_null($url)) {
        $url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
    } elseif ($url) {
        $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : (string)\think\facade\Route::buildUrl($url);
    }

    $result = [
        'code' => 2,
        'msg' => $msg,
        'data' => $data,
        'url' => $url,
        'wait' => $wait,
    ];
    $type = getResponseType();

    if ('html' == strtolower($type)) {
        $type = 'view';
        $response = response(think\facade\View::display(public_path("static") . "dispatch_jump.html", $result), 200, $header, $type);
    } else {
        $response = think\Response::create($result, $type)->header($header);
    }

    // throw new think\exception\HttpResponseException($response);
    return $response;
}

/**
 * 权限 function
 *
 * @param boolean $is_page
 * @param string $child_name
 * @return array
 */
function appAttribute(bool $is_page = true, string $child_name = "child"): array
{
    $controllerPath = app()->getAppPath() . request()->layer()  . DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR;
    $controller_suffix = config("route.controller_suffix") ? "Controller" : ""; // 控制器后缀
    $controllers = glob($controllerPath . '*.php');
    $arr = [];
    $i = 0;
    foreach ($controllers as $files) {
        // 根据文件路径是被类名
        /** @var  $class_name *根据文件路径获取类名 */
        $class_name = "app\\" . str_replace('/', '\\', substr(substr($files, strlen(base_path())), 0, -4));

        if (!class_exists((string)$class_name)) {
            // echo "Class $class_name not found, skip route for it\n";
            continue;
        }

        $controller = new \ReflectionClass((string)$class_name);
        $controllerClass = $controller->getAttributes(app\common\Attribute::class);
        $title = $controllerClass[0]->newInstance()->title();

        $ClassShortName = str_replace($controller_suffix, "", $controller->getShortName());
        $arr[$i] = ["name" => $ClassShortName, "title" => $title, "spread" => true, "key" => $ClassShortName];

        foreach ($controller->getMethods(\ReflectionMethod::IS_PUBLIC) as $v) {
            /** 淘汰方法 */
            if (in_array($v->name, ['__construct', '__destruct'])) {
                continue;
            }
            // echo $v->class;
            $controller_str = str_replace($controller_suffix, "", $controller->getShortName()); //控制器名
            $controller_name = app\common\Util::strislower($controller_str); //控制器路径

            $class = new \ReflectionMethod($v->class, $v->name);
            $attributes = $class->getAttributes(app\common\Attribute::class);
            $method_name = $v->name; //方法名

            if (empty($attributes)) {
                continue;
            }
            foreach ($attributes as $attribute) {
                if ($data = array_merge([
                    "name" => ($MethodShortName = $v->name),
                    "spread" => true,
                    "key" => "$ClassShortName@$MethodShortName"
                ], $attribute->newInstance()->fun())) {
                    $arr[$i][$child_name][] =  $data;
                }
            }
        }
        ++$i;
    }
    $UserAuth = session('auth');
    $info = [];
    foreach ($arr as $v) {
        if (isset($v[$child_name]) && !empty($v[$child_name]) && !in_array($v["name"], ["IndexController", "LoginController"])) {
            $cc_arr = [];
            foreach ($v[$child_name] as $kk => $vv) {
                if ($UserAuth["rid"] > 0) {
                    $AuthArr = json_decode($UserAuth["auth"], true); //已拥有的权限
                    if ($vv["isAuth"] && $is_page) {
                        if (in_array($vv["key"], $AuthArr)) {
                            if ($vv["isPage"]) {
                                $cc_arr[] = $vv;
                            }
                        }
                    } else {
                        $cc_arr[] = $vv;
                    }
                } else {
                    if ($is_page) {
                        if ($vv["isPage"]) {
                            $cc_arr[] = $vv;
                        }
                    } else {
                        $cc_arr[] = $vv;
                    }
                }
            }
            $v[$child_name] = $cc_arr;
        } else {
            continue;
        }
        if (!empty($v[$child_name])) {
            $info[] = $v;
        }
    }
    return $info;
}

/**
 * 树形数组 function
 *
 * @param array $data
 * @param integer $parentId
 * @return array
 */
function buildTree(array $data, int $parentId = 0): array
{
    $tree = array();

    foreach ($data as $item) {
        if ($item['pid'] == $parentId) {
            $children = buildTree($data, $item['id']);

            if (!empty($children)) {
                $item['children'] = $children;
            }
            $item["icon"] = $item["icon_str"];
            $item["title"] = $item["name"];
            if ($item["is_menu"] == 1) {
                $firstChar = strtolower(substr($item["controller"], 0, 1));
                $restOfString = substr($item["controller"], 1);
                $controller = $firstChar . $restOfString;
                $item["href"] = (string)url("admin." . $controller  . "." . $item["method"]);
            }
            $tree[] = $item;
        }
    }

    return $tree;
}

/**
 * select无限树形 function
 *
 * @param array $data
 * @param integer $pid
 * @param array $array
 * @param integer $level
 * @param string $separator
 * @return void
 */
function selectTree(array $data = [], int $pid = 0, array &$array = [], $level = 0, $separator = '&nbsp;&nbsp;|---->'): array
{
    foreach ($data as $key => $value) {
        if ($value['pid'] == $pid) {
            $value['level'] = str_repeat($separator, $level); //分隔符修改处,并非一定要当形参引用传入,也可以写死来提升美观性,这里为了便于理解所以当作了形参处理
            $array[] = $value;
            selectTree($data, $value['id'], $array, $level + 1);
        }
    }
    return $array;
}

/**
 * 递归删除文件 function
 *
 * @param string $folder 文件夹路径
 * @return void
 */
function deleteFolder(string $folder)
{
    if (is_dir($folder)) {
        $files = scandir($folder);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                deleteFolder($folder . '/' . $file);
            }
        }
        rmdir($folder);
    } else {
        unlink($folder);
    }
}

function imgEsc(string $str): string
{
    return str_replace("\\", "/", $str);
}


/**
 * 自定义排序函数 function
 *
 * @param array $a
 * @param array $b
 * @return integer
 */
function compare(array $a, array $b): int
{
    if ($a['px'] == $b['px']) {
        return 0;
    }
    return ($a['px'] > $b['px']) ? -1 : 1;
}
